package org.jawa.learning.dao.ibatis;

import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Map;

import org.apache.ibatis.builder.xml.dynamic.ForEachSqlNode;
import org.apache.ibatis.executor.ErrorContext;
import org.apache.ibatis.executor.ExecutorException;
import org.apache.ibatis.mapping.BoundSql;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.ParameterMapping;
import org.apache.ibatis.mapping.ParameterMode;
import org.apache.ibatis.reflection.MetaObject;
import org.apache.ibatis.reflection.property.PropertyTokenizer;
import org.apache.ibatis.session.Configuration;
import org.apache.ibatis.session.RowBounds;
import org.apache.ibatis.type.TypeHandler;
import org.apache.ibatis.type.TypeHandlerRegistry;
import org.jawa.core.exception.UserNotFoundException;
import org.jawa.core.log.Log;
import org.jawa.learning.dao.UserDao;
import org.jawa.learning.model.Role;
import org.jawa.learning.model.User;
import org.jawa.learning.webapp.util.Page;
import org.springframework.orm.ObjectRetrievalFailureException;
import org.springframework.stereotype.Repository;

/**
 * 用户信息相关数据库操作实现类，用于对用户信息的修改与查询。
 * 
 * @author YAK
 */
@Repository("userDao")
public class UserDaoiBatis extends GenericDaoiBatis<User, Long> implements UserDao {

	public UserDaoiBatis() {
		super(User.class);
	}

	@Override
	public User get(Long userId) {
		User user = (User) getSqlSession().selectOne("getUser", userId);
		if (user == null) {
			log.warn("uh oh, user not found...");
			throw new ObjectRetrievalFailureException(User.class, userId);
		} else {
			List roles = getSqlSession().selectList("getUserRoles", userId);
			user.setRoles(new HashSet<Role>(roles));
		}

		return user;
	}

	/**
	 * {@inheritDoc}
	 */
	public List<User> getUsers() {
		List<User> users = getSqlSession().selectList("UserSQL.getUsers", null);
		// 查询人员的角色信息
		for (int i = 0; i < users.size(); i++) {
			User user = (User) users.get(i);

			List<Role> roles = getSqlSession().selectList("getUserRoles", user.getId());
			user.setRoles(new HashSet<Role>(roles));
			users.set(i, user);
		}
		return users;
	}

	@Override
	public Page<User> getUsers(User user, Page<User> page) {
		if (page.getTotalItems() < 0) {
			Integer usersCount = getSqlSession().selectOne("countGetUsers", user);
			page.setTotalItems(usersCount);
		}

		List<User> users = getSqlSession().selectList("getUsers", user,
				new RowBounds(page.getOffset(), page.getPageSize()));
		// 查询人员的角色信息
		for (int i = 0; i < users.size(); i++) {
			User obj = (User) users.get(i);

			List<Role> roles = getSqlSession().selectList("getUserRoles", obj.getId());
			obj.setRoles(new HashSet<Role>(roles));
			users.set(i, obj);
		}
		page.setResult(users);
		return page;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public User saveUser(final User user) {
		iBatisDaoUtils.prepareObjectForSaveOrUpdate(user);
		int id = getSqlSession().insert("addUser", user);
		//addUserRoles(user);
		return user;
	}

	/**
	 * {@inheritDoc}
	 * @throws Exception 
	 */
	@Override
	public User updateUser(final User user) throws Exception {
		try{
			getSqlSession().update("updateUserSelective", user);
		}catch(Exception ex){
			Log.error("更新用户", ex);
			throw ex;
		}
		//deleteUserRoles(user.getId());
		//addUserRoles(user);
		return user;
	}

	/**
	 * Convenience method to delete roles
	 * 
	 * @param userId
	 *            the id of the user to delete
	 */
	private void deleteUserRoles(Long userId) {
		getSqlSession().delete("deleteUserRoles", userId);
	}

	private void addUserRoles(final User user) {
		if (user.getRoles() != null) {
			for (Role role : user.getRoles()) {
				Map<String, Long> newRole = new HashMap<String, Long>();
				newRole.put("userId", user.getId());
				newRole.put("roleId", role.getId());

				List userRoles = getSqlSession().selectList("getUserRoles", user.getId());
				if (userRoles.isEmpty()) {
					getSqlSession().update("addUserRole", newRole);
				}
			}
		}
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public void remove(Long userId) {
		deleteUserRoles(userId);
		getSqlSession().delete("deleteUser", userId);
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public User loadUserByUsername(String username) throws UserNotFoundException {
		User user = (User) getSqlSession().selectOne("getUserByUsername", username);
		if (user == null) {
			log.warn("uh oh, user not found...");
			throw new ObjectRetrievalFailureException(User.class, username);
		} else {
			List roles = getSqlSession().selectList("getUserRoles", user.getId());
			user.setRoles(new HashSet<Role>(roles));
		}
		return user;
	}

	/**
	 * {@inheritDoc}
	 */
	@Override
	public String getUserPassword(String username) {
		return (String) getSqlSession().selectOne("UserSQL.getUserPassword", username);
	}

}
